package io.github.heollhai.common.config.security.handler;

import com.alibaba.fastjson2.JSON;
import io.github.heollhai.common.basic.BasicDuration;
import io.github.heollhai.common.basic.BasicKey;
import io.github.heollhai.common.entity.security.dto.UserByRoleDto;
import io.github.heollhai.common.utils.HttpServletRequestUtils;
import io.github.heollhai.common.utils.JWTUtil;
import io.github.heollhai.common.config.reids.RedisOperator;
import io.github.heollhai.common.utils.VerifyUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * @Author: lmf
 * @Create: 2024/8/6 15:06
 * Description:token认证过滤器
 */
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    @Resource
    private RedisOperator redisOperator;

    @Override
    protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response,
                                    @NonNull FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(BasicKey.HEADER_TOKEN);
        if (StringUtils.isEmpty(token)) {
            SecurityContextHolder.getContext().setAuthentication(null);
            // 把授权的控制交给下级处理
            filterChain.doFilter(request, response);
        } else {
            String _token = JWTUtil.checkJwt(token);
            String userInfo = redisOperator.get(BasicKey.REDIS_USER_TOKEN + _token);
            // 判断token是否过期
            if (_token == null || VerifyUtils.isEmpty(userInfo)) {
                SecurityContextHolder.getContext().setAuthentication(null);
                // 把授权的控制交给下级处理
                filterChain.doFilter(request, response);
                return;
            }
            // 构建认证信息
            SecurityContextHolder.getContext().setAuthentication(buildAuthentication(_token, request));
            filterChain.doFilter(request, response);
        }
    }

    private Authentication buildAuthentication(String _token, HttpServletRequest request) {
        String browserInfo = HttpServletRequestUtils.getBrowserInfo(request, BasicKey.REDIS_USER_TOKEN);

        // 检测token是否过期
        if(redisOperator.keyIsExist(browserInfo + _token)){
            // 获取公共的用户信息
            UserByRoleDto userByRoleDto = redisOperator.get(BasicKey.REDIS_USER_TOKEN +  _token,
                    UserByRoleDto.class);
            if (userByRoleDto == null) {
                return null;
            }

            // 更新token时间
            // 更新公共的用户登录信息到 redis
            redisOperator.set(BasicKey.REDIS_USER_TOKEN + userByRoleDto.getNameAndId(),
                    JSON.toJSONString(userByRoleDto), BasicDuration.TOKEN_DURATION);

            // 更新用户 redis token 过期时间
            redisOperator.set(browserInfo + userByRoleDto.getNameAndId(), BasicKey.DEFAULT_VALUE,
                    BasicDuration.TOKEN_DURATION);

            // 更新刷新token时间
            redisOperator.expire(BasicKey.REDIS_USER_REFRESH_TOKEN + browserInfo + userByRoleDto.getNameAndId(),
                    BasicDuration.REFRESH_TOKEN_DURATION);

            // 根据redis中的用户信息 设置用户权限 构建用户信息
            return new UsernamePasswordAuthenticationToken(userByRoleDto, null, userByRoleDto.getAuthorities());
        }
        return null;
    }
}

